#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         Assessment.py
#
# Copyright:    Copyright (c) 2005, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  An Assessment is storage-agnostic in-memory 
#               representation of the state of an assessment, 
#               information of which is typically captured during 
#               the process of 'performing an assessment' against a Model.
#
#               This implementation is lazy, in that it delays the
#               actual retrieving of assessment information from
#               an AssessmentStorageService until required.
#
#               To create, retrieve, update or delete an 
#               Assessment, you should use the AssessmentStorageService.
#
#               NOTE 1: Instances of this class should ALWAYS be pickleable
#               as to permit storage of an assessment by python pickling.
#               An example usage: Temporarily storing an assessment in
#               a Zope HTTP Session
#
#               NOTE 2: This class replaces the 0.x branch class
#               AssessmentCache.  The difference being that this
#               implementation is storage independant where as 
#               AssessmentCache was tightly coupled with the MySQL
#               implementation.
#
#               NOTE 3: This class additionally supports the notion
#               of 'Assessment Attributes' that may be used to persist
#               state that is not directly related to individual component
#               state.  For example: The score for an assessment may
#               be 'cached' as an assessment attribute to avoid expensive
#               recalculation.  The principle concept of assessment
#               attributes is that they may be dropped at any time, 
#               without effecting the semantics of the actual 
#               assessment state captured while 'performing an assessment'
#
# See Also:     Assessible, AssessmentComponentValueTypes,
#               AssessmentComponentState, AssessmentAttribute,
#               AssessmentStorageService
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Common import *
from Core import *
from KERFProcessor import resolveKERF

#####################################################################
## Zope Library Imports
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
from AccessControl.Role import RoleManager
from DateTime import DateTime
 
#####################################################################
## Python Library Imports
import os
import time

#####################################################################
## Python Logging Configuration
import logging
log = logging.getLogger("KnowledgeEngine.Assessment")

#####################################################################
## Assessment Class Definition
class Assessment(RoleManager):
    """
        A lazily in-memory storage-agnostic representation of an
        Assessment.
    """
        
    #---------------------------------------------------------------#

    #declare security so ClassInfo may be accessed in DTML/ZPT etc
    security = ClassSecurityInfo()
    security.declareObjectPublic()
    security.setDefaultAccess("allow")

    #---------------------------------------------------------------#

    def __init__(self, assessmentIdentity, model, openedByUserIdentity = None, openedFromRepositoryIdentity = None, revision=None):
        """
            Assessments are constructed using using four properties;
            * The identity of the assessment
            * The model to which the assessment pertains
        """
        
        
        ### the following attributes are generally not persisted - they are transient        
        #a dictionary of AssessmentComponentState instances, for Assessible components indexed by ComponentIdentity.
        #{Component.getIdentity -> AssessmentComponentState}
        self.componentState = {}
        
        #a dictionary of AssessmentAttribute instances, indexed by AssessmentAttributeHandle.getAttributeIdentity()
        #{AssessmentAttributeHandle.getAttributeIdentity() -> AssessmentAttribute}
        self.attributes = {}        
        self.openedBy = openedByUserIdentity
        self.openedFromRepositoryIdentity = openedFromRepositoryIdentity
        
        ### the following attributes are generally stored together (and need to be persisted)
        self.identity = assessmentIdentity
        self.model = model                          #only the model.getIdentity() is actually persisted
        self.instantCreated = DateTime()            
        self.instantModified = DateTime()          
        self.createdBy = 'anonymous'                #who created the assessment 
        self.responsible = 'anonymous'
        self.isLocked = false                       #once locked an assessment may not be changed
        self.name = '(new assessment)'              #the user-friendly/provided name for the assessment
        self.checkedOutBy = None                    #the user identity that has the assessment checkedout (or None)
        self.creditTransactionIdentity = None       #the credit transaction used to create the assessment (or None)
        
        self.isNew = true
        self.isModified = true
        
        self.revision = int(revision or 0)


    #---------------------------------------------------------------#
    def createNewRevision(self, user=None):
        """
            Create a new revision for the assessment
        """
                
        self.revision += 1

        return int(self.revision)
    
    
    #---------------------------------------------------------------#
    def getRevision(self):
        """ Returns the assessment revision, or None if defaulting to 'latest'  """
        
        return self.revision
    
    
    #---------------------------------------------------------------#
    def setRevision(self, revision):
        """
            Sets the revision number for this assessment
        """
        
        self.revision = int(revision)

    #---------------------------------------------------------------#
    
    def getLatestRevisionNumber(self):
        """ Returns the latest revision number for this assessment """
        
        return self.getStorageService().getLatestAssessmentRevision(self.getIdentity())
        
    
    #---------------------------------------------------------------#

    def getIdentity(self):
        """
            Returns the unique identity for the assessment
            
            RETURN TYPE: String
        """
        
        return self.identity

    #---------------------------------------------------------------#
    
    def setIdentity(self, assessmentIdentity):
        """ Sets this assessments identity """
        
        self.identity = assessmentIdentity
    
    #---------------------------------------------------------------#

    def getModel(self):
        """
            Returns the Model for the assessment.
            
            RETURN TYPE: Model Class            
        """
        
        return self.model

    #---------------------------------------------------------------#

    def getModelIdentity(self):
        """
            Returns the Model identity for the assessment.
            
            RETURN TYPE: String
        """
        
        return self.model.getIdentity()

    #---------------------------------------------------------------#

    def getOpenedBy(self):
        """
            Returns the Knowledge Engine User Identity that opened the 
            assessment.  May return None if the system (or someone unknown)
            opened the assessment.
            
            NOTE: Not persistent

            RETURN TYPE: String (UserIdentity)
        """
        
        return self.openedBy

    #---------------------------------------------------------------#

    def getOpenedFromRepositoryIdentity(self):
        """
            Returns the identity of the repository from which 
            the assessment was opened/created.
            
            May return None if the opening repository is unknown.
            
            NOTE: Not persistent

            RETURN TYPE: String
        """
        
        return self.openedFromRepositoryIdentity

    #---------------------------------------------------------------#

    def getStorageService(self):
        """
            RETURNS: The AssessmentStorageService that may be used
            to persist the assessment
        """

        #lookup the assessment storage service        
        return self.getModel().getAssessmentStorageService()

    #---------------------------------------------------------------#
    
    def save(self):
        """ Saves this assessment """
        
        self.getStorageService().saveAssessment( self )
    
    
    
    #---------------------------------------------------------------#

    def getInstantCreated(self):
        """
            Returns the instant in time (as a DateTime) that the assessment was created
            
            RETURN TYPE: DateTime   
        """

        return self.instantCreated

    #---------------------------------------------------------------#

    def setInstantCreated(self, instantCreated):
        """
            Sets the instant in time (as a DateTime) that the assessment was created
        """

        self.instantCreated = instantCreated

    #---------------------------------------------------------------#

    def getInstantModified(self):
        """
            Returns the instant in time (as a DateTime) that the assessment was modified
            
            RETURN TYPE: DateTime
        """

        return self.instantModified

    #---------------------------------------------------------------#

    def setInstantModified(self, instantModified):
        """
            Sets the instant in time (since the EPOCH) that the assessment was modified
        """

        self.instantModified = instantModified
        
    #---------------------------------------------------------------#
    
    def getResponsible(self):
        """
            Returns the User Identity that created the assessment
        
            RETURN TYPE: String
        """
        
        return self.responsible

    #---------------------------------------------------------------#

    def setResponsible(self, userIdentity):
        """
            Sets the user identity that created the assessment
        """
        
        print "Setting responsible for %s  to %s" % (self.getIdentity(), userIdentity)
        
        self.responsible = userIdentity
        self.setIsModified(true)
            
    
    #---------------------------------------------------------------#

    def getCreatedBy(self):
        """
            Returns the User Identity that created the assessment
        
            RETURN TYPE: String
        """
        
        return self.createdBy

    #---------------------------------------------------------------#

    def setCreatedBy(self, userIdentity):
        """
            Sets the user identity that created the assessment
        """
        
        self.createdBy = userIdentity
        self.setIsModified(true)
        
    #---------------------------------------------------------------#

    def getCheckedOutBy(self):
        """
            Returns the User Identity that has the assessment checkedout
            (None if not checkedout)
        
            RETURN TYPE: String
        """
        
        return self.checkedOutBy

    #---------------------------------------------------------------#

    def setCheckedOutBy(self, userIdentity):
        """
            Sets the user identity that has the assessment checkedout
        """
        
        if userIdentity == "":
            self.checkedOutBy = None
        else:
            self.checkedOutBy = userIdentity 
            
        self.setIsModified(true)
        
    #---------------------------------------------------------------#

    def isCheckedOut(self):
        """
            Returns if this assessment is currently checkedout.
            
            This includes logic to determine 
        """
        
        #we only need to check if the model doesn't allow concurrent assessment
        if not self.getModel().getPermitsConcurrentAssessment():

            #does the assessment think it's checked out?
            if self.getCheckedOutBy() is not None and self.getCheckedOutBy() != "":

                #has enough time passed since the last modification to warrant that the assessment may not be checkedout?
                if self.getInstantModified().lessThan(DateTime().timeTime() - (getMaximumAssessmentCheckoutTime() * 60)):
                    #outside the time period now... so assume not checked out
                    return false
                else:
                    #still within the timeout period
                    return true                

            #not checked out
            else:
                return false            
        
        #doing concurrent assessment so multiple users permitted
        else:
            return false
        
    #---------------------------------------------------------------#

    def getCreditTransactionIdentity(self):
        """
            Returns the Credit Transaction Identity that was used
            to create the assessment (may return '' or None).
            
            This is used to track/audit the consumption of credits
            when creating assessment.  It's also used when refunding
            credits after deleting assessments created using credits.
        
            RETURN TYPE: String
        """
        
        return self.creditTransactionIdentity

    #---------------------------------------------------------------#

    def setCreditTransactionIdentity(self, creditTransactionIdentity):
        """
            Sets the Credit Transaction Identity that was used
            to create the assessment (may return '' or None).
        """
        
        self.creditTransactionIdentity = creditTransactionIdentity
        self.setIsModified(true)

    #---------------------------------------------------------------#

    def getIsLocked(self):
        """
            Returns if the assessment is locked
            
            RETURN TYPE: Boolean
        """

        return self.isLocked

    #---------------------------------------------------------------#

    def setIsLocked(self, isLocked):
        """
            Sets if the assessment is locked
            
            NOTE: If you lock or unlock an assessment, you MUST
            ensure the Model.onBeforeLock/UnlockAssessment is called
            prior to saving the assessment to ensure correct
            events are handled.
        """

        self.isLocked = isLocked
        self.setIsModified(true)

    #---------------------------------------------------------------#

    
        
        

    def getName(self):
        """
            Returns the user provided name for the assessment
        
            RETURN TYPE: String
        """
        
        # FIXME: This method shouldn't return (unnamed) - that should be part of the view template.
        
        model = self.getModel()
        template = model.getAssessmentTitleTemplate()
        
        if template:
            if template.startswith('script:'):
                scriptName = template[7:]
                script     = getattr(model, scriptName)
            
                return script(assessment=self) or "(unnamed)"
            else:
                #return "(Foo)"           
                return resolveKERF( template, self ) or "(unnamed)"
            
        else:
            #if the name is empty, return "(unnamed)"
            if self.name is None or self.name == "":
                return "(unnamed)"
            else:            
                return self.name 

    #---------------------------------------------------------------#

    def setName(self, name):
        """
            Sets the user provided name for the assessment
        """
        
        self.name = name
        self.setIsModified(true)

    #---------------------------------------------------------------#
    
    def allowRename(self):
        """ Can this assessment be renamed """
        
        template = self.getModel().getAssessmentTitleTemplate()
        if template:
            return False
        else:
            return True
    
    #---------------------------------------------------------------#

    def getIsNew(self):
        """
            Returns if the assessment state is new (not yet persisted)
            
            RETURN TYPE: Boolean
        """

        return self.isNew

    #---------------------------------------------------------------#

    def setIsNew(self, isNew):
        """
            Sets if the assessment state is new (not yet persisted)
        """

        self.isNew = isNew

    #---------------------------------------------------------------#

    def getIsModified(self):
        """
            Returns if the assessment state has been modified since created or loaded 
            
            RETURN TYPE: Boolean
        """

        if self.isModified:
            return true
        else:
            # Check is any of the component state's has changed
            self.setIsModified( self.hasModifiedComponentStates() )

            return self.isModified
            
    #---------------------------------------------------------------#

    def setIsModified(self, isModified):
        """
            Sets if the assessment state has been modified since created or loaded 
        """

        self.isModified = isModified
            
    #---------------------------------------------------------------#
    
    def getSearchIndexValue(self, searchIndex, default=None, isMulti=False):
        """ 
            Returns the value of the specified searchIndex
        """
        
        # Check the currently loaded component states in memory- These may not have been committed yet.
        states = self.getComponentStates()
        
        searched = []
        
        for state in states:
            mySearchIndex = state.getSearchIndex()
            mySearchValue = state.getSearchValue()
            
            if (mySearchValue) and (mySearchIndex == searchIndex):
                return mySearchValue
            
            searched.append( state.getComponentIdentity() )
        
        # Nothing found, try checking the database. 
        # we pass ignoreComponents to make sure we don't pull an old value from the database if the uncommitted in-memory version
        # has been set to null in the current transaction
        storageService = self.getModel().knowledgeengine_assessmentstorageservice
        return storageService.getAssessmentSearchIndexValue( self, searchIndex, default=default, isMulti=isMulti, ignoreComponents=searched )
        
        
                
    #---------------------------------------------------------------#
    
    def getComponentByIdValue(self, id):
        """
            Returns the value of the first component found with the specified id 
        """
        
        model = self.getModel()
        
        catalog = model.knowledgeengine_genericobjectcatalogservice
        rs = catalog( getModelIdentity=model.getIdentity(), getId=id)
        if not rs: return None
        
        object = rs[0].getObject()
        
        return object.getComponentValue( assessment=self )
        
        #state = self.getComponentState(object.getIdentity())
        #return state.getValue()


    #---------------------------------------------------------------#

    def getComponentByIdentityValue(self, componentIdentity):
        """
            Returns the value for the component with the specified identity
        """
            
        catalog = self.getModel().knowledgeengine_genericobjectcatalogservice
        rs = catalog( getIdentity=componentIdentity )
        if not rs: 
            print "Could not find component %s" % `componentIdentity`
            return None
        
        object = rs[0].getObject()
            
        return object.getComponentValue( assessment=self )
            
        #state = self.getComponentState(componentIdentity)
        #return state.getValue()
    
    #---------------------------------------------------------------#

    def getComponentByIdentityReportContent(self, componentIdentity):
        """
            Returns the report content for the component with the specified identity
        """
            
        component = self.getModel().getComponentByIdentity( componentIdentity )
        value     = component.getComponentValue( assessment=self )
            
        return component.getReportContentForValue( assessment=self )
    #---------------------------------------------------------------#

    def setComponentState(self, componentIdentity, componentState):
        """
            Sets the state of the specified component 
            (an instance of AssessmentComponentState).  
        """

        #set the component state
        self.componentState[componentIdentity] = componentState

        #the cache has been modified
        self.setIsModified(true)
            
    #---------------------------------------------------------------#

    def getComponentState(self, componentIdentity):
        """
            Retrieves the state of the specified component.
            (an instance of the AssessmentComponentState).
            
            If the assessment does not have state for the component,
            The 'default state' for the component is added to the 
            assesment.
            
            RETURN TYPE: AssessmentComponentState
        """
        
        starttime = time.clock()
        
        #is the state in the component?
        if self.componentState.has_key(componentIdentity):
        
            #get the state from the internal cache
            assessmentComponentState = self.componentState[componentIdentity]
        
        else:
            #attempt to get the state from the AssessmentStorageService
            storageService = self.getStorageService()
             
            #if we can, load the state from the storage tool?
            assessmentComponentState = None
            if storageService is not None:
                #(load the state using the storageService)                
                assessmentComponentState = storageService.loadComponentState(self, componentIdentity)
                            
            #did we load it?
            if assessmentComponentState is None:            
                #(use the default assessment state from the component itself)
                #get the component from the model
                component = self.getModel().getComponent(componentIdentity)
                            
                # FIXME: Define exceptions properly
                if not component:
                    raise Exception, "Could not find component with identity " + `componentIdentity`

                #get the default state of the component from the component itself (using this assessment)
                assessmentComponentState = component.getDefaultAssessmentState(self)
                assessmentComponentState.setRevision(self.getRevision())
                assessmentComponentState.setIsModified( False ) # By defauly, components states should be marked as not modified
            
            #add the state to the assessment
            self.componentState[componentIdentity] = assessmentComponentState

        endtime = time.clock()

        log.debug("%s:(%d): %s" % (sys._getframe().f_code.co_name, sys._getframe().f_lineno, "Loaded Component State in %f" % (endtime-starttime)))        

        return assessmentComponentState         

    #---------------------------------------------------------------#

    def getComponentStates(self, forceLoad=false):
        """
            Retrieves a list of all of the currently cached component states
            
            NOTE: does not forcibly load all of the component states
            for the model (this implementation is lazy)
        """
            
        if forceLoad:
            model = self.getModel()
            components = model.getDescendantsByInstanceOf('Assessible')
            for component in components:
                self.getComponentState( component.getIdentity() )

        return self.componentState.values()
            
    #---------------------------------------------------------------#

    def hasModifiedComponentStates(self):
        """
            Returns true if this assessment has components whose state has
            changed.
        """

        result = false
        for state in self.getComponentStates():
            result = result or state.getIsModified()
        
        return result

    #---------------------------------------------------------------#

    def getComponentCSVValues(self, displayReportContent=False):
        """
            Return the CSV friendly values of this assessment keyed
            to their component identity
            
            RETURN: {...}
        """

        result = {}
        for component in self.getModel().getOrderedExportables():
            result[component.getIdentity()] = component.getComponentCSVValue(self, displayReportContent=displayReportContent)

        return result

    #---------------------------------------------------------------#

    def getAttributes(self):
        """
            Retrieves a list of all of the currently cached attributes
            
            NOTE: does not forcibly load all of the component states
            for the model (this implementation is lazy)
        """
            
        return self.attributes.values()
            
    #---------------------------------------------------------------#

    def setAttribute(self, assessmentAttribute):
        """
            Sets the state of the specified attribute 
            (an instance of AssessmentAttribute).  
        """

        # Set the component state
        self.attributes[assessmentAttribute.getAttributeHandle().getAttributeIdentity()] = assessmentAttribute

        # The cache has been modified
        self.setIsModified(true)
            
    #---------------------------------------------------------------#

    def getAttribute(self, attributeHandle):
        """
            Retrieves the state of the specified attribute.
            (an instance of the AssessmentAttribute).
            
            If the assessment does not have the specified attribute,
            None is returned.
            
            RETURN TYPE: AssessmentAttribute
        """
        
        #is the attribute in the attributes collection?
        if self.attributes.has_key(attributeHandle.getAttributeIdentity()):
        
            #get the attribute from the internal cache
            assessmentAttribute = self.attributes[attributeHandle.getAttributeIdentity()]
        
        else:
            #attempt to get the attribute from the AssessmentStorageService
            storageService = self.getStorageService()
            
            #if we can, load the attribute from the storage service?
            assessmentAttribute = None
            if storageService is not None:
                #(load the attribute using the storageService)
                assessmentAttribute = storageService.loadAttribute(self, attributeHandle)
            
            #add the attribute to the internal cache (if it's not None!)
            if assessmentAttribute is not None:
                self.attributes[attributeHandle.getAttributeIdentity()] = assessmentAttribute

        return assessmentAttribute         
               
    #---------------------------------------------------------------#
    
    def getRepositories(self):
        """ Returns a list of repositories this assessment is in """
        
        ass = self.getStorageService()
        
        identities = ass.getRepositoriesForAssessment( self )
        
        return filter(None,[ass.getComponentByIdentity( identity ) for identity in identities])
        
    #---------------------------------------------------------------#        

    def getRepositoryIdentities(self):
        """ Returns a list of repositories this assessment is in """
        
        ass = self.getStorageService()
        
        return ass.getRepositoriesForAssessment( self )
        
    #---------------------------------------------------------------#        


    def isOrphaned(self):
        """
            Returns True if the assessment is not in any repository
            i.e. it is orphaned
        """

        if len(self.getRepositories()) > 0:
            return False

        return True
        
    #---------------------------------------------------------------#        
        
        
    def getAssessmentActions( self, user, repositoryOnly=False ):
        """ Returns a list of available assessment actions on this assessment for the specified user 
            params:-
                user: Username to filter actions on
                repositoryOnly: Only show actions in a repository (i.e. excluding the model root)
        """
        
        repositories = self.getRepositories()
        actions = []
        for repo in repositories:
            actions.extend( repo.getAssessmentActions( user ) or [] )
            
        if not repositoryOnly:            
            
            model = self.getModel()
            actions.extend( model.getAssessmentActions(user) or [])            
            
        return actions

        
    #---------------------------------------------------------------#
    def getTags(self):
        """
            Return any tags that have been given to this assessment
        """
        
        model = self.getModel()
        if not model.isTaggable():
            return []
        
        return self.getStorageService().getTagsForAssessment(self)

        
    #---------------------------------------------------------------#
    def setTags(self, tagString, user = None):
        """
            Add tags (given by the tagString) to this assessment
        """

        return self.getStorageService().setTagsForAssessment(self, tagString, user)

        
    #---------------------------------------------------------------#
    def removeTags(self, tagString, user = None):
        """
            Remove tags from this assessment
        """

        return self.getStorageService().removeTagsFromAssessment(self, tagString, user)

        
    #---------------------------------------------------------------#
    
    def canEdit( self, user=None ):
        """ Can the specified user (or current) edit this assessment? """
        
        model = self.getModel() # Grab the model (Primarily to use as context)
        context = model
        
        securityservice   = context.knowledgeengine_securityservice                    
        assessmentstorage = context.knowledgeengine_assessmentstorageservice
        
        
    
        if not user:
            #user = context.REQUEST.AUTHENTICATED_USER
            user = context.portal_membership.getAuthenticatedMember()
            
        user_id = str(user)
                        
        repositoryIdentities = assessmentstorage.getRepositoriesForAssessment( self )
        
        #raise `repositoryIdentities`
        
        if self.hasPermission('EditAssessmentsInPersonalRepository', user) and user_id in repositoryIdentities:            
            return True
        
        if self.hasPermission('EditRepositoryAssessments', user):
            return True
            
        if self.hasPermission('EditAnyAssessment', user):
            return True
        
    #---------------------------------------------------------------#        
        
    def canView( self, user=None ):
        """ Can the specified user (or current) view this assessment? """
        
        model = self.getModel() # Grab the model (Primarily to use as context)
        context = model
        
        securityservice   = context.knowledgeengine_securityservice                    
        assessmentstorage = context.knowledgeengine_assessmentstorageservice
        
       
        if not user:
            #user = context.REQUEST.AUTHENTICATED_USER
            user = context.portal_membership.getAuthenticatedMember()
            
        user_id = str(user)
                        
        repositoryIdentities = assessmentstorage.getRepositoriesForAssessment( self )
        
        #raise `repositoryIdentities`
        
        if self.hasPermission('AccessRepository', user):            
            return True
    
    #---------------------------------------------------------------#

    def hasPermission(self, permission, user=None):
        """ Checks if the specified user (Or currently authenticated user) has
            the specified permission on this assessment
            
            permission[string]: Name of permission
            user[string]: Name of user. Leave as None for currently authenticated user
        """
        
        model = self.getModel() # Grab the model (Primarily to use as context)
        context = model
        
        if not user:
            user = context.portal_membership.getAuthenticatedMember() 
            #user = context.REQUEST.AUTHENTICATED_USER
            
        user_id = str(user)
            
            
        securityservice   = context.knowledgeengine_securityservice                    
        assessmentstorage = context.knowledgeengine_assessmentstorageservice
            
        repositoryIdentities = assessmentstorage.getRepositoriesForAssessment( self )
        #repositoryIdentities.append( user_id )
            
        # Hack - AccessRepository doesn't work for Personal repositories, however 
        # Caller functions will need us to assume it does, so hard code that case. 
        if permission == 'AccessRepository' and user_id in repositoryIdentities:
            return True
            
        # Iterate over each repository this assessment is in, and check for the permission.
        # If any is granted, bail with a True. If not, keep going until we finish with a False.
        for repositoryIdentity in repositoryIdentities + [model.getIdentity()]:
            
            
            
            access = securityservice.getEffectivePermission( permission, repositoryIdentity, user_id )
           
           
            # Access Granted
            if access and access.granted(assessment=self):
                return True
        
        # No permissions found
        return False
        
    #---------------------------------------------------------------#

        
    #---------------------------------------------------------------#
    
#     def getLinksTo( self ):
#         """ Returns all links to this assessment """
#         
#         ass = self.knowledgeengine_assessmentstorageservice
#         return ass.getLinksToAssessment( self.getIdentity()
#     
#     #---------------------------------------------------------------#    
#         
#     def getLinksFrom( self ):
#         """ Returns all links from this assessment """
#         
#         ass = self.knowledgeengine_assessmentstorageservice
#         return ass.getLinksFromAssessment( self.getIdentity()        
        
        
#####################################################################
## Class Initialisation
InitializeClass(Assessment)
